package plugins.brush_plugin;

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JLabel;

import dymnd.image.Layer;
import dymnd.io.ConfigHashtable;
import dymnd.net.Packet;
import dymnd.plugin.PaintPlugin;
import dymnd.ui.SeekBar;
import dymnd.ui.ThemeConstants;


//import net.java.games.jogl.*;

public class EPC extends PaintPlugin{
	
	Line2D.Double lastLine = null;
	ConfigHashtable config;
	
	//JLabel label = new JLabel("<html><body text=white><p>Size: </p></body></html>");
	
	
	double drawAlpha = 1;
	BufferedImage backbuf;
	
	SeekBar alphaSeekbar = new SeekBar(255);
	SeekBar sizeSeekbar = new SeekBar(200);
	int lastValidX = -1;
	int lastValidY = -1;
	
	public EPC()	{
		
		
		
		alphaSeekbar.setBackground(ThemeConstants.THEME_SEEKER_BACKGROUND_COLOR);
		alphaSeekbar.setSeekBarColor(ThemeConstants.THEME_SEEKER_BAR_COLOR);
		alphaSeekbar.setBorder(BorderFactory.createEtchedBorder(Color.lightGray, Color.darkGray));
		
	}
	
	public ImageIcon getIcon()	{
		return new ImageIcon(loadImage("plugins/brush_plugin/brushicon.png"));
	
	}
	public Container getToolbar(Dimension d)	{
		Container c = new Container();
		c.setLocation(0, 0);
		c.setSize(d.getSize());
		int labelWidth = 50;
		int componentHeight = 20;
		
		int sizeSeekbarWidth = 150;
		int opacitySeekbarWidth = 100;
		
		int x = 10;
		
		JLabel sizeLabel = new JLabel("Size: ");
		JLabel opacityLabel = new JLabel("Opacity: ");
		
		//size seekbar
		sizeLabel.setSize(30, componentHeight);
		sizeLabel.setLocation(x, (int)(d.getHeight()/2 - sizeLabel.getHeight()/2));
		sizeLabel.setForeground(ThemeConstants.THEME_PLUGIN_PANEL_TEXT_COLOR);
		sizeLabel.setFont(ThemeConstants.FONT_PLUGIN_TOOLBAR_COMPONENT);
		c.add(sizeLabel);
		
		sizeSeekbar.setSize(sizeSeekbarWidth, componentHeight);
		sizeSeekbar.setLocation(x += sizeLabel.getWidth(),(int)(d.getHeight()/2 - sizeSeekbar.getHeight()/2));
		sizeSeekbar.setPercent(10);
		c.add(sizeSeekbar);
		
		//opacity seekbar 
		opacityLabel.setSize(labelWidth, componentHeight);
		opacityLabel.setLocation(x += sizeSeekbar.getWidth() + 10, (int)(d.getHeight()/2 - sizeLabel.getHeight()/2));
		opacityLabel.setForeground(ThemeConstants.THEME_PLUGIN_PANEL_TEXT_COLOR);
		opacityLabel.setFont(ThemeConstants.FONT_PLUGIN_TOOLBAR_COMPONENT);
		c.add(opacityLabel);
		
		alphaSeekbar.setSize(opacitySeekbarWidth, componentHeight);
		alphaSeekbar.setLocation(x += opacityLabel.getWidth(),(int)(d.getHeight()/2 - alphaSeekbar.getHeight()/2));
		c.add(alphaSeekbar);
		
		
		return c;
	}
	
	
	boolean strokeStart = true;
	BasicStroke stroke;
	int smallestX = 0;
	int smallestY = 0;
	
	int largestX = 0;
	int largestY = 0;
	int alpha = 0;
	
	int stepping = 20;
	int radiusStepping = 1;
	
	
	public Packet onEvent(Packet p, Layer affectedLayer, Layer scratchLayer)	{
		int radius = (int)sizeSeekbar.getValue();
		if(strokeStart)	{
			
			p.lastX = p.x;
			p.lastY = p.y;
			
			smallestX = p.x;
			smallestY = p.y;
			largestX = p.x;
			largestY = p.y;
		}	else	{
			
			
			
		}
		
		
		if(p.x > largestX && p.x > 0)
			largestX = p.x;
		
		if(p.y > largestY && p.y > 0)
			largestY = p.y;
		
		if(p.x < smallestX && p.x >= 0)
			smallestX = p.x;
		
		if(p.y < smallestY && p.y >= 0)
			smallestY = p.y;
		
		
		
		
		if(p.primaryColor.getAlpha() == 0)
			alpha = (int)alphaSeekbar.getValue();
		else	
			alpha = p.primaryColor.getAlpha();
		
		
		//System.out.println(p.x);
		//paint the first stroke
		stroke = new BasicStroke((int)(sizeSeekbar.getValue()*p.pressure), BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);
		Graphics2D g = scratchLayer.createGraphics();
		g.setComposite(AlphaComposite.Src);
		g.setColor(new Color(p.primaryColor.getRed(), p.primaryColor.getGreen(), p.primaryColor.getBlue(), (int)alphaSeekbar.getValue()));
		
		g.setStroke(stroke);
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		
		
		g.draw(new Line2D.Double(p.x, p.y, p.lastX, p.lastY));
		
		/*stroke = new BasicStroke((int)(sizeSeekbar.getValue()*p.pressure - radiusStepping), BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);
		g.setStroke(stroke);
		g.setColor(new Color(p.color.getRed(), p.color.getGreen(), p.color.getBlue(), (int)alphaSeekbar.getValue() - stepping));
		g.draw(new Line2D.Double(p.x, p.y, p.lastX, p.lastY));*/
		
		int x = Math.min(p.x, p.lastX) - radius;
		int y = Math.min(p.y, p.lastY) - radius;
		
		/*if(p.lastX < 0)
			p.lastX = p.x;
		if(p.lastY < 0)
			p.lastY = p.y;*/
	
		if(x < 0)
			x = 0;
		if(y < 0)
			y = 0;
		
		int width = Math.max(p.x, p.lastX) - x;
		int height = Math.max(p.y, p.lastY) - y;
		
		width = width + radius;
		height = height + radius;
		
		if(width <= 0)
			width = 1+radius*2;
		if(height <= 0)
			height = 1+radius*2;
		
		//System.out.println("X: " + x + " Y: " + y + " Width: " + width +  " Height: " + height);
		//System.out.println(affectedLayer.getWidth() + " " + affectedLayer.getHeight());
		
		//System.out.println(boundsRect.getX() + " " + boundsRect.getY());
		strokeStart = false;
		scratchLayer.setModified(true);
		
		if(p.mouseAction == Packet.MOUSE_ACTION_RELEASED)	{
			
			smallestX = smallestX - radius;
			smallestY = smallestY - radius;
			
			largestX = largestX + radius*2;
			largestY = largestY + radius*2;
			
			if(smallestX < 0)
				smallestX = 0;
			if(smallestY < 0)
				smallestY = 0;
			
			if(largestX  > affectedLayer.getWidth())
				largestX = affectedLayer.getWidth();
			
			if(largestY > affectedLayer.getHeight())
				largestY = affectedLayer.getHeight();
			//System.out.println(largestX + " " + largestY);
			g = affectedLayer.createGraphics();
			int releasedWidth = largestX - smallestX;
			int releasedHeight = largestY - smallestY;
			if(releasedWidth <= 0)
				releasedWidth = 1;
			if(releasedHeight <= 0)
				releasedHeight = 1;
				
			
			try	{
				g.drawImage(scratchLayer.getSubimage(smallestX, smallestY, releasedWidth, releasedHeight), smallestX, smallestY, null);
			}	catch(Exception e)	{
				e.printStackTrace();
				System.exit(1);
			}
			scratchLayer.clear();
			strokeStart = true;
			p.bounds = new Rectangle2D.Double(smallestX, smallestY, releasedWidth, releasedHeight);
			return p;
		}
		
		if(x < 0)
			x = 0;
		if(y < 0)
			y = 0;
		
		//does check for width+x and height+y
		if(x + width > affectedLayer.getWidth())	{
			width = width + (affectedLayer.getWidth() - (x+width));
		}
		
		if(y + height > affectedLayer.getHeight())	{
			height = height + (affectedLayer.getHeight() - (y+height));
		}
		
		if(width <= 0)	{
			x = affectedLayer.getWidth() - 2;
			width = 1;
		}
		
		if(height <= 0)	{
			y = affectedLayer.getHeight() - 2;
			height = 1;
		}
		
		p.bounds = new Rectangle2D.Double(x, y, width, height);
		return p;
	}
	
	
	
	
	public boolean usingDefaultCursor()	{
		return true;
	}
	
	public String getTooltip()	{
		return "A simple brush tool";
	}
	
	public String getVersionString()	{
		return "brush_plugin.version.1.0";
	}
	
	
	public char getKeyChar()	{
		return 'b';
	}
	
	
	private Image loadImage(String file)	{
		return Toolkit.getDefaultToolkit().getImage(file);
	}
	
	public void onUnload()	{
		/*config.set("brushRadius",	"" + (Double)sizeSeekbar.getValue());
		config.set("alpha", "" + (Double)alphaSeekbar.getValue());*/
	}
	
}

class ThickLine extends Area	{
	
	public ThickLine(int startX, int startY, int endX, int endY, int rad)	{
		double x1 = Math.min(startX, endX);
		double x2 = Math.max(startX, endX);
		double y1 = Math.min(startY, endY);
		double y2 = Math.max(startY, endY);
		
		//add the line's rectangle
		Rectangle2D.Double rect = new Rectangle2D.Double(startX, startY, x2 - x1, rad*2);
		add(new Area(rect));
		
		//find the angle of the line, in Radians
		double angle = Math.atan2((double)(y2 - y1), (double)(x2 - x1));
		System.out.println("Angle: " + angle);
		transform(AffineTransform.getRotateInstance(angle, startX, startY));
	}
	
	
}

